﻿using FPSO.Models.Constant;
using FPSO.Models.Domain;
using FPSO.Models.ViewModel.Controls;
using Org.BouncyCastle.Asn1.X509;
using PrismMVVMLibrary.DesignTime;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FPSO.Models.Constant.TankConstant;

namespace FPSO.Services.Impl
{
    public class TaskTankCalcService : ITaskTankCalcService
    {
        private ITankTaskService taskService;

        public TaskTankCalcService(ITankTaskService taskService)
        {
            this.taskService = taskService;
        }

        public TankTask getPreTask(int queueId)
        {
            List<TankTask> tankTaskList = taskService.GetWaitAndExecingCheckingTaskList(queueId);
            var sortTaskList = tankTaskList.OrderBy(o => o.PlanEndTime).ToList();

            if (sortTaskList.Count == 0) return null;

            return sortTaskList[sortTaskList.Count - 1];
        }

		public List<Dictionary<string, double>> GetAllTankVolume(TankTask lastTankTask)
        {
			List <Dictionary<string, double>> res = new List<Dictionary<string, double>>();

            List<TaskTankTimeFlagDetail> taskTankVolumes = GetAllTaskTankDetails(lastTankTask);
			foreach(TaskTankTimeFlagDetail taskTankVolume in taskTankVolumes)
			{
				Dictionary<string, double> res0 = new Dictionary<string, double>();

				foreach (TankVolumeDetail tankVolume in taskTankVolume.tankVolumeDetails)
				{
					//tankVolume.TankCurrentVolume是变化量，当res0不包含目标TankId是新建，否则叠加体积变化量
					if (!res0.ContainsKey(tankVolume.TankId))
					{
						double currentVolume = tankVolume.TankInitVolume + tankVolume.TankCurrentVolume;
						res0.Add(tankVolume.TankId, currentVolume);
					}
					else
					{
						double currentVolume = res0[tankVolume.TankId] + tankVolume.TankCurrentVolume;
						res0[tankVolume.TankId] = currentVolume;
					}

					if (res0[tankVolume.TankId] > tankVolume.TankTotleVolume)
						res0[tankVolume.TankId] = tankVolume.TankTotleVolume;
					else if (res0[tankVolume.TankId] < 0)
						res0[tankVolume.TankId] = 0;
				}
				res.Add(res0);
			}
			return res;
		}

		//计算当前所有任务的相关舱室及液位状态
		public List<TaskTankTimeFlagDetail> GetAllTaskTankDetails(TankTask lastTankTask)
        {
            List<TaskTankTimeFlagDetail> taskTankTimeFlagDetails = new List<TaskTankTimeFlagDetail> ();
            //获取所有任务信息
            List<TankTask> tankTaskList = taskService.GetAllWaitAndExecingAndCheckingTaskList();

			//lastTankTask如果是针对已有工况的更新，则已存在于tankTaskList中，无需重复添加
			if (lastTankTask != null)
			{
				bool findcheck = false;
				foreach(TankTask task in tankTaskList)
				{
					if(task.TaskId == lastTankTask.TaskId)
					{
						findcheck = true;
						break;
					}
				}
				if(!findcheck)
					tankTaskList.Add(lastTankTask);
			}

			var sortTaskList = tankTaskList.OrderBy(o => o.PlanStartTime).ToList();

            //初始化舱室信息及容量
            Dictionary<String, TankVolumeDetail> tankVolumeDict = new Dictionary<String, TankVolumeDetail>();

            //所有任务关键时间点列表
            List<DateTime> keyTimeFlagList = new List<DateTime>();

            //遍历所有任务建立时间列表,初始化舱室液位信息
            foreach (TankTask task in sortTaskList)
            {
                keyTimeFlagList.Add(task.PlanStartTime);
                keyTimeFlagList.Add(task.PlanEndTime);

				int taskid = task.TaskId;

				//初始化油舱
				//tankVolumeDict中保存的id改成当前Taskid和Tankid的拼接
				string[] tankdis = task.TankId.Split(',');
				foreach (string tankid in tankdis)
				{
					TankVolumeDetail tankVolumeDetail = new TankVolumeDetail();
					tankVolumeDetail.TankId = tankid;
					tankVolumeDetail.TankName = TankConstant.GetTankName(tankid);
					tankVolumeDetail.TankTotleVolume = TankConstant.GetTankVolume(tankid);
					tankVolumeDetail.TankInitVolume = task.InitVolm * tankVolumeDetail.TankTotleVolume / 100;
					tankVolumeDetail.TankCurrentVolume = 0;
					tankVolumeDetail.TankPipeSpeed = task.PipeSpeed;
					//tankVolumeDetail.TankTargetVolume = task.TargetVolm * 0.01 * tankVolumeDetail.TankTotleVolume;
					string dict_id = $"{tankid},{taskid}";
					tankVolumeDict.Add(dict_id, tankVolumeDetail);
					//tankVolumeDict.Add(tankid, tankVolumeDetail);
				}

				//初始化压载舱
				foreach (WBTTask wtask in task.WBTTaskList)
                {
                    if (!tankVolumeDict.ContainsKey(wtask.WBTTankId))
                    {
                        TankVolumeDetail wTankVolumeDetail = new TankVolumeDetail();
						//wTankVolumeDetail.TankId = $"{wtask.WBTTankId},{taskid}";
						wTankVolumeDetail.TankId = wtask.WBTTankId;
						wTankVolumeDetail.TankName = TankConstant.GetTankName(wtask.WBTTankId);
						//DEBUG 这里有问题，压载舱的初始状态数据库未保存，后续节点校核无法计算压载舱的状态
						wTankVolumeDetail.TankTotleVolume = TankConstant.GetTankVolume(wtask.WBTTankId);
						wTankVolumeDetail.TankInitVolume = 0 * wTankVolumeDetail.TankTotleVolume / 100;
						wTankVolumeDetail.TankCurrentVolume = 0;
						//wTankVolumeDetail.TankTargetVolume = wtask.TargetVolume * 0.01 * wTankVolumeDetail.TankTotleVolume;
						wTankVolumeDetail.TankPipeSpeed = wtask.PipeSpeed;
						string dict_id = $"{wtask.WBTTankId},{taskid}";
						tankVolumeDict.Add(dict_id, wTankVolumeDetail);
						//tankVolumeDict.Add(wtask.WBTTankId, wTankVolumeDetail);
					}
				}
            }

            keyTimeFlagList.Sort();

			foreach (DateTime keyTime in  keyTimeFlagList)
            {
                TaskTankTimeFlagDetail taskTankTimeFlagDetail = new TaskTankTimeFlagDetail();
                taskTankTimeFlagDetail.TimeFlag = keyTime;
                taskTankTimeFlagDetail.tankVolumeDetails = new List<TankVolumeDetail>();

				//计算每隔舱室在关键时间点上的液位信息
				foreach (TankTask task in sortTaskList)
                {
                    if (keyTime < task.PlanStartTime || keyTime > task.PlanEndTime)
                    {
                        continue;
                    }
					if (task.TaskType == TaskTypeConstant.LOAD_ID)
                    {
                        calcLoadTask(task, keyTime, tankVolumeDict);
                    }
                    else if (task.TaskType == TaskTypeConstant.UNLOAD_ID)
                    {
                        calcOutTask(task, keyTime, tankVolumeDict);
                    }
                    else if (task.TaskType == TaskTypeConstant.SWAP_ID)
                    {
                        calcSwapTask(task, keyTime, tankVolumeDict);
                    }
				}
				foreach (string tankId in tankVolumeDict.Keys)
				{
					taskTankTimeFlagDetail.tankVolumeDetails.Add(tankVolumeDict[tankId].Copy());
				}
				taskTankTimeFlagDetails.Add(taskTankTimeFlagDetail);
			}
			return taskTankTimeFlagDetails;
        }

        //油舱装载计算
        public void calcLoadTask(TankTask task, DateTime keyTime, Dictionary<String, TankVolumeDetail> tankVolumeDict)
        {
            string[] tankdis = task.TankId.Split(',');
			int taskid = task.TaskId;
            foreach (string tankid in tankdis)
            {
				string dict_id = $"{tankid},{taskid}";
				TankVolumeDetail tankVolumeDetail = tankVolumeDict[dict_id];
				//TankVolumeDetail tankVolumeDetail = tankVolumeDict[tankid];
				if (tankVolumeDetail != null)
                {
                    double passHour = (keyTime - task.PlanStartTime).TotalHours;
                    //tankVolumeDetail.TankInitVolume = tankVolumeDetail.TankInitVolume + task.PipeSpeed * passHour;

					tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankPipeSpeed * passHour;
					//if (tankVolumeDetail.TankCurrentVolume > tankVolumeDetail.TankTotleVolume)
     //               {
     //                   tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankTotleVolume;
     //               }
                }
            }
            calcWBTTask(task, keyTime, tankVolumeDict);
        }

        //油舱卸载计算
        public void calcOutTask(TankTask task, DateTime keyTime, Dictionary<String, TankVolumeDetail> tankVolumeDict)
        {
            string[] tankdis = task.TankId.Split(',');
			int taskid = task.TaskId;
			foreach (string tankid in tankdis)
            {
				string dict_id = $"{tankid},{taskid}";
				//TankVolumeDetail tankVolumeDetail = tankVolumeDict[tankid];
				TankVolumeDetail tankVolumeDetail = tankVolumeDict[dict_id];
				if (tankVolumeDetail != null)
                {
                    double passHour = (keyTime - task.PlanStartTime).TotalHours;
                    //tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankCurrentVolume - task.PipeSpeed * passHour;
					tankVolumeDetail.TankCurrentVolume = - tankVolumeDetail.TankPipeSpeed * passHour;
					//if (tankVolumeDetail.TankCurrentVolume < 0)
     //               {
     //                   tankVolumeDetail.TankCurrentVolume = 0;
     //               }
                }
            }
            calcWBTTask(task, keyTime, tankVolumeDict);
        }


        //油舱倒舱计算
        public void calcSwapTask(TankTask task, DateTime keyTime, Dictionary<String, TankVolumeDetail> tankVolumeDict)
        {
            string[] tankdis = task.TankId.Split(',');
			int taskid = task.TaskId;
			double passHour = (keyTime - task.PlanStartTime).TotalHours;

            foreach (string tankid in tankdis)
            {
				string dict_id = $"{tankid},{taskid}";
				//TankVolumeDetail tankVolumeDetail = tankVolumeDict[tankid];
				TankVolumeDetail tankVolumeDetail = tankVolumeDict[dict_id];
				if (tankVolumeDetail != null)
                {
                    //tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankCurrentVolume - task.PipeSpeed * passHour;
					tankVolumeDetail.TankCurrentVolume = - tankVolumeDetail.TankPipeSpeed * passHour;
					//if (tankVolumeDetail.TankCurrentVolume < 0)
     //               {
     //                   tankVolumeDetail.TankCurrentVolume = 0;
     //               }
                }
            }
            string[] tanktargetdis = task.SwapTargetTank1.Split(',');
            foreach (string tanktargetid in tanktargetdis)
            {
				string dict_id = $"{tanktargetid},{taskid}";
				//TankVolumeDetail tankVolumeDetail = tankVolumeDict[tanktargetid];
				TankVolumeDetail tankVolumeDetail = tankVolumeDict[dict_id];
				if (tankVolumeDetail != null)
                {
                    //tankVolumeDetail.TankInitVolume = tankVolumeDetail.TankInitVolume + task.PipeSpeed * passHour;
					tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankPipeSpeed * passHour;
					//if (tankVolumeDetail.TankCurrentVolume > tankVolumeDetail.TankTotleVolume)
     //               {
     //                   tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankTotleVolume;
     //               }
                }
            }

            calcWBTTask(task, keyTime, tankVolumeDict);
        }

        //压载舱计算入口
        public void calcWBTTask(TankTask task, DateTime keyTime, Dictionary<String, TankVolumeDetail> tankVolumeDict)
        {
            foreach(WBTTask wbtTask in task.WBTTaskList)
            {
                if (wbtTask.IsLoad)
                {
					calcWBTLoad(wbtTask, task, keyTime, tankVolumeDict);
                }
                else
                {
					calcWBTUnLoad(wbtTask, task, keyTime, tankVolumeDict);
                }
            }
        }

        //压载装舱计算
        public void calcWBTLoad(WBTTask wbttask, TankTask task, DateTime keyTime, Dictionary<String, TankVolumeDetail> tankVolumeDict)
        {
			int taskid = task.TaskId;
			string dict_id = $"{wbttask.WBTTankId},{taskid}";
			//TankVolumeDetail tankVolumeDetail = tankVolumeDict[wbttask.WBTTankId];
			TankVolumeDetail tankVolumeDetail = tankVolumeDict[dict_id];
			if (tankVolumeDetail != null)
            {
                double passHour = (keyTime - task.PlanStartTime).TotalHours;
                //tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankCurrentVolume + task.PipeSpeed * passHour;
				tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankPipeSpeed * passHour;
				//if (tankVolumeDetail.TankCurrentVolume > tankVolumeDetail.TankTotleVolume)
    //            {
    //                tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankTotleVolume;
    //            }
            }     
        }

        //压载卸舱计算
        public void calcWBTUnLoad(WBTTask wbttask, TankTask task, DateTime keyTime, Dictionary<String, TankVolumeDetail> tankVolumeDict)
        {
			int taskid = task.TaskId;
			string dict_id = $"{wbttask.WBTTankId},{taskid}";
			//TankVolumeDetail tankVolumeDetail = tankVolumeDict[task.WBTTankId];
			TankVolumeDetail tankVolumeDetail = tankVolumeDict[dict_id];
			if (tankVolumeDetail != null)
            {
                double passHour = (keyTime - task.PlanStartTime).TotalHours;
                //tankVolumeDetail.TankCurrentVolume = tankVolumeDetail.TankCurrentVolume - task.PipeSpeed * passHour;
				tankVolumeDetail.TankCurrentVolume = - tankVolumeDetail.TankPipeSpeed * passHour;
				//if (tankVolumeDetail.TankCurrentVolume < 0)
    //            {
    //                tankVolumeDetail.TankCurrentVolume = 0;
    //            }
            }
        }
    }
}
